/************************************************************************************
 *                                                                                  *
 *                                                                                  *
 ************************************************************************************/
package jMiiEditor.gui;

import jMiiEditor.deprecated.swing.SwingHelpers;
import jMiiEditor.gui.checker.JMiiEditorCheckJDialog;
import jMiiEditor.gui.doc.AboutDialog;
import jMiiEditor.gui.doc.HelpDialog;
import jMiiEditor.gui.miifilechooser.MiiFileChooser;
//import jMiiEditor.gui.miifilechooser.MiiFileChooserDefaultImpl;
import jMiiEditor.gui.miifilechooser.MiiFileChooserDefaultImpl;
import jMiiEditor.gui.miifilechooser.MiiFileChooserVFSImpl;
import jMiiEditor.gui.miifilechooser.MiiFileObject;
import jMiiEditor.gui.miifilechooser.MiiFileObjectDefaultImpl;
import jMiiEditor.gui.preferences.JMiiEditorPreferenceJDialog;
import jMiiEditor.gui.preferences.Preferences;
import jMiiEditor.gui.swingintrospection.MiiSwingIntrospectorObjectInterface;
import jMiiEditor.i18n.I18nBundle;
import jMiiEditor.mii.Mii;
import jMiiEditor.mii.checker.MiiChecker;
import jMiiEditor.mii.checker.MiiCheckerDefault;
import jMiiEditor.mii.checker.MiiCheckerFileObject;
import jMiiEditor.mii.checker.MiiCheckerResult;
import jMiiEditor.mii.introspection.MiiGetterIntrospectionItem;
import jMiiEditor.myavatareditor.JDKVersionDesktopNotSupportedException;
import jMiiEditor.myavatareditor.MyAvavatarEditorDisplay;
import jMiiEditor.myavatareditor.PlateformeDesktopNotSupportedException;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import javax.swing.Box;
import javax.swing.JFileChooser;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import org.apache.log4j.Logger;
import com.googlecode.cchlib.i18n.AutoI18n;
import com.googlecode.cchlib.i18n.I18n;
import com.googlecode.cchlib.swing.filechooser.DefaultConfigurator;
import com.googlecode.cchlib.swing.filechooser.JFileChooserInitializer;
import com.googlecode.cchlib.swing.filechooser.accessory.BookmarksAccessory;
import com.googlecode.cchlib.swing.filechooser.accessory.DefaultBookmarksAccessoryConfigurator;
import com.googlecode.cchlib.swing.filechooser.accessory.TabbedAccessory;

import cx.ath.choisnet.lang.introspection.IntrospectionException;
import cx.ath.choisnet.swing.helpers.LookAndFeelHelpers;
import cx.ath.choisnet.swing.introspection.SwingIntrospector;
import cx.ath.choisnet.swing.introspection.SwingIntrospectorException;

public class JMiiEditorMainJFrame
     extends JMiiEditorMainJFrameVS4E
{
    private static Logger slogger = Logger.getLogger(JMiiEditorMainJFrame.class);
    private static final long serialVersionUID = 1L;

    private SwingIntrospector<JMiiEditorMainJFrame,Mii,MiiGetterIntrospectionItem> introspection;
    private Mii                 mii_;
    private MiiFileObject       miiFileObject;
    private MiiFileChooser      miiFileChooser;
    private String              miiFileChooserLookAndFeelClassName;
    private Preferences         preferences = new Preferences();
    private AutoI18n            autoI18n = I18nBundle.getAutoI18n();

    private JFileChooserInitializer  jFileChooserInitializer;

    @I18n private String txtErrorWhileCreateMiiObject = "Error while Mii Object.";

    public JMiiEditorMainJFrame()
    {
        super(); //initComponents();

        this.introspection = new SwingIntrospector<JMiiEditorMainJFrame,Mii,MiiGetterIntrospectionItem>( new MiiSwingIntrospectorObjectInterface() );
        this.jFileChooserInitializer = getJFileChooserInitializer();

        try {
            preferences.load();
            }
        catch( IOException e ) {
            e.printStackTrace();
            }

        try {
            introspection.initComponentsWithException( this );
            }
        catch( SwingIntrospectorException e ) {
            throw new RuntimeException( e );
            }

        // fix some bugs in VS4E
        jCheckBox_Girl$root$0.setHorizontalAlignment(SwingConstants.RIGHT);
        jCheckBox_Girl$root$0.setHorizontalTextPosition(SwingConstants.LEFT);
        jCheckBox_Girl$root$1.setHorizontalAlignment(SwingConstants.RIGHT);
        jCheckBox_Girl$root$1.setHorizontalTextPosition(SwingConstants.LEFT);
        jCheckBox_HairPartReversed$root.setHorizontalAlignment(SwingConstants.RIGHT);
        jCheckBox_HairPartReversed$root.setHorizontalTextPosition(SwingConstants.LEFT);
        jCheckBox_MingleOff$root.setHorizontalAlignment(SwingConstants.RIGHT);
        jCheckBox_MingleOff$root.setHorizontalTextPosition(SwingConstants.LEFT);

        // set some stuff not yet automate
        limitedIntegerJTextField_MiiId$root$0.setRadix(16);
        limitedIntegerJTextField_MiiId$root$1.setRadix(16);
        limitedIntegerJTextField_MiiId$root$2.setRadix(16);
        limitedIntegerJTextField_MiiId$root$3.setRadix(16);
        limitedIntegerJTextField_SystemId$root$0.setRadix(16);
        limitedIntegerJTextField_SystemId$root$1.setRadix(16);
        limitedIntegerJTextField_SystemId$root$2.setRadix(16);
        limitedIntegerJTextField_SystemId$root$3.setRadix(16);

        // Dynamique part
        jMenuItem1CheckMii.setEnabled( false );
        jMenuItem0Save.setEnabled( false );

        jMenuItem1ShowMii.setEnabled(
            MyAvavatarEditorDisplay.isSupported()
            );

        InputStream is = getClass().getResourceAsStream("/jMiiEditor/gui/default.mii");

        if( is != null ) {
            try {
                this.mii_ = new Mii( is );

                this.populate();
            }
            catch( IOException e ) {
                // TODO Auto-generated catch block
                slogger.fatal( e );
            }
        }

        // Apply i18n !
        performeI18n( autoI18n );

        // initDynComponents
        LookAndFeelHelpers.buildLookAndFeelMenu( this, this.jMenu3LookAndFeel );
    }

    /**
     * Apply i18n
     * @param autoI18n
     */
    public void performeI18n(AutoI18n autoI18n)
    {
        autoI18n.performeI18n(this,this.getClass());
    }

    @Override
    protected JMenuBar getJMenuBar$Frame()
    {
        if (jMenuBar$Frame == null) {
            jMenuBar$Frame = new JMenuBar();
            jMenuBar$Frame.add(getJMenu0File());
            jMenuBar$Frame.add(getJMenu1Tools());
            jMenuBar$Frame.add(getJMenu2Help());
            jMenuBar$Frame.add(Box.createHorizontalGlue());
            jMenuBar$Frame.add(getJMenu3LookAndFeel());
        }
        return jMenuBar$Frame;
    }

    /**
     * Main entry of the class.
     * Note: This class is only created so that you can easily preview the result at runtime.
     * It is not expected to be managed by the designer.
     * You can modify it as you like.
     * @param args
     * @throws IOException
     * @throws FileNotFoundException
     */
    public static void main(String[] args) throws FileNotFoundException, IOException
    {
        final MiiFileObject aMiiFileObject;

        slogger.info( "---------------------------" );
        slogger.info( slogger.getEffectiveLevel() );
        slogger.info("main args:" + (args==null?args:args.length) );

        if( args != null && args.length == 1 ) {
            slogger.info("args[0]=" + args[0]);
            aMiiFileObject = new MiiFileObjectDefaultImpl( new File( args[0] ));
        }
        else {
            aMiiFileObject = null;
        }

        installLnF();
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JMiiEditorMainJFrame frame = new JMiiEditorMainJFrame();
                frame.setDefaultCloseOperation(JMiiEditorMainJFrame.EXIT_ON_CLOSE);
                frame.setTitle("JMiiEditor");
                frame.getContentPane().setPreferredSize(frame.getSize());
                if( aMiiFileObject != null ) {
                    try {
                        frame.setMiiFileObject( aMiiFileObject );
                    }
                    catch( IOException e ) {
                        // TODO Auto-generated catch block
                        slogger.fatal( e );
                    }
                    //frame.populate();
                }
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
                //frame.initDynComponents();
                }
        });
    }

    // -------------------------------------------------------------------
    // Events handlers
    // -------------------------------------------------------------------
    @Override
    protected void windowWindowClosing(WindowEvent event)
    {
        slogger.info( "windowWindowClosing" );
    }

    @Override
    protected void windowWindowClosed(WindowEvent event)
    {
        slogger.info( "windowWindowClosed" );
        //TODO: confirm ?
        // check if Mii has change ?
        // populate a tmp mii and compare to internal mii
    }

    @Override
    protected void jMenuItem0QuitMouseMousePressed(MouseEvent event)
    {
        windowWindowClosed(null);
        dispose();
        System.exit(0);
    }

    @Override
    protected void jMenuItem0Save_MouseMousePressed(MouseEvent event)
    {
        if( jMenuItem0Save.isEnabled() ) {
            saveMiiFileObject();
        }
    }

    @Override
    protected void jMenuItem0SaveAs_MouseMousePressed(MouseEvent event)
    {
        try {
            MiiFileObject res = getMiiFileChooser().showSaveDialogExt( this );

            if( res != null ) {
                setMiiFileObject( res );
                saveMiiFileObject();
            }
        }
        catch( Exception e ) {
            slogger.warn( "Error while getting new file !", e );
            SwingHelpers.showMessageDialog(this, "Select saving file", e );
        }
    }

    @Override
    protected void jMenuItem0Open_MouseMousePressed(MouseEvent event)
    {
        try {
            MiiFileObject aMiiFileObject = getMiiFileChooser().showOpenDialogExt(this);

            if( aMiiFileObject != null ) {
                setMiiFileObject( aMiiFileObject );
                //this.mii = aMiiFileObject.loadMii();
                //populate();
            }
        } catch (Exception e) {
            slogger.warn( "Error while getting new file !", e );
            SwingHelpers.showMessageDialog(this, "Openning", e );
        }
    }

    @Override
    protected void jMenuItem1CheckMii_MouseMousePressed(MouseEvent event)
    {
        if( jMenuItem1CheckMii.isEnabled()) {
            checkMii();
        }
    }

    @Override
    protected void showMii()
    {
        try {
            new MyAvavatarEditorDisplay( getMii() ).showMii();
        }
        catch( CantCreateMiiException e ) {
            // Well, just log !
            slogger.fatal( e );
        }
        catch( PlateformeDesktopNotSupportedException e ) {
            // TODO Auto-generated catch block
            slogger.fatal( e );
        }
        catch( JDKVersionDesktopNotSupportedException e ) {
            // TODO Auto-generated catch block
            slogger.fatal( e );
        }
    }

    @Override
    protected void jMenuItem1Preferences_MouseMousePressed(MouseEvent event)
    {
        JMiiEditorPreferenceJDialog dialog = new JMiiEditorPreferenceJDialog(this);

        dialog.setPreferences( preferences );
        dialog.setLocationRelativeTo(this);
        dialog.setModal( true );
        dialog.setVisible( true );

        preferences = dialog.getPreferences();
        try {
            preferences.save();
        }
        catch( IOException e ) {
            // TODO Auto-generated catch block
            slogger.fatal( e );
        }
    }

    @Override
    protected void jMenuItem2HelpMouseMousePressed(MouseEvent event)
    {
        HelpDialog dialog = new HelpDialog(this);
        dialog.setLocationRelativeTo(this);
        dialog.setModal( false );
        dialog.setVisible(true);
    }

    @Override
    protected void jMenuItem2AboutMouseMousePressed(MouseEvent event)
    {
        AboutDialog dialog = new AboutDialog(this);
        dialog.setLocationRelativeTo(this);
        dialog.setModal( true );
        dialog.setVisible(true);
    }

    // -------------------------------------------------------------------
    // Save
    // -------------------------------------------------------------------
    private void saveMiiFileObject()
    {
        boolean saveFile;

        if( getFileObject().exists() ) {
            String   filename = getFileObjectDisplayPath();
            Object[] options = { "Yes", "No" };
            int n = JOptionPane.showOptionDialog( this, "File " + filename
                    + " already exist.", "Overwrite ?",
                    JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE,
                    null, options, options[ 1 ] );

            saveFile = (n == 0);
        } else {
            saveFile = true;
        }

        this.introspection.populateObjectWithoutException( this, this.mii_ );

        if( saveFile ) {
            String filename = getFileObjectDisplayPath();

            try {
                getFileObject().saveMii( mii_ );

                JOptionPane.showMessageDialog(
                    this,
                    "File " + filename + " saved.",
                    "Saving",
                    JOptionPane.PLAIN_MESSAGE
                    );
            }
            catch( Exception e ) {
                slogger.warn( "Error while saving: " + filename, e);
                SwingHelpers.showMessageDialog(this, "Saving", e );
            }
        }
    }

    // -------------------------------------------------------------------
    //
    // -------------------------------------------------------------------

    private void populate()
    {
        if( this.mii_ != null ) {
            this.introspection.populateFrameWithoutException( this, this.mii_ );
        }
    }

    private void checkMii()
    {
        MiiChecker  checker = null;

        try {
            checker = new MiiChecker( getMii() );
        }
        catch( CantCreateMiiException e ) {
            // Well, just log and quit
            e.printStackTrace();
            return;
        }
        final String filename = getFileObjectName();

         checker.performAllChecks(
               new MiiCheckerDefault()
               {
                    @Override
                    public byte[] getSystemId()
                    {
                        return preferences.getSystemId();
                    }
                    @Override
                    public String getFileName()
                    {
                        return filename;
                    }
               }
               );

        if( checker != null ) {
            JMiiEditorCheckJDialog dialog  = new JMiiEditorCheckJDialog(this);
            dialog.setTableModel( checker );

            if( miiFileObject != null ) {
                dialog.setFileName( getFileObjectDisplayPath() );
            }

            //dialog.initI18n( this.i18n );
            autoI18n.performeI18n(dialog,JMiiEditorCheckJDialog.class);
            dialog.setModal( true );
            dialog.setVisible( true );
            System.out.println( "JMiiEditorCheckJDialog: " + dialog );

            MiiCheckerFileObject aMiiCheckerFileObject = getMiiCheckerFileObject();

            if( checker.getMiiCheckerResults().size() == 0 ) {
                // Nothing to do, bye, bye...
                return;
            }

            MiiCheckerResult miiCheckerResult = checker.apply( aMiiCheckerFileObject );

            if( miiCheckerResult != null ) {
                try {
                    setMiiFileObject( miiCheckerResult.getMiiCheckerFileObject() );
                }
                catch( IOException e ) {
                    // TODO Auto-generated catch block
                    slogger.fatal( e );
                }
            }
            else {
                slogger.fatal( "MiiCheckerResult == null" );
            }

//            try {
//                this.introspection.populateFrameWithException( this, this.mii );
//            }
//            catch( SwingIntrospectorException e ) {
//                e.printStackTrace();
//            }
//            catch( IntrospectionInvokeException e ) {
//                // TO DO Auto-generated catch block
//                e.printStackTrace();
//            }

            if( miiCheckerResult != null ) {
                dialog = new JMiiEditorCheckJDialog(this);
                dialog.setTableModel( miiCheckerResult );

                if( miiFileObject != null ) {
                    dialog.setFileName( getFileObjectDisplayPath() );
                }
                //dialog.initI18n( this.i18n );
                autoI18n.performeI18n(dialog,JMiiEditorCheckJDialog.class);
                dialog.setModal( true );
                dialog.setVisible( true );
             }
        }
    }

    public Mii getMii() throws CantCreateMiiException
    {
        try {
            this.introspection.populateObjectWithException( this, this.mii_ );
        }
        catch( SwingIntrospectorException e ) {
            SwingHelpers.showMessageDialog(
                    this,
                    txtErrorWhileCreateMiiObject,
                    e
                    );
            throw new CantCreateMiiException(e);
        }
        catch( IntrospectionException e ) {
            SwingHelpers.showMessageDialog(
                    this,
                    txtErrorWhileCreateMiiObject,
                    e
                    );
            throw new CantCreateMiiException(e);
        }

        return mii_;
    }

    private JFileChooserInitializer getJFileChooserInitializer()
    {
        if( jFileChooserInitializer == null ) {
            jFileChooserInitializer = new JFileChooserInitializer(
                // new JFileChooserInitializer.DefaultConfigurator() {
                new DefaultConfigurator() {
                    private static final long serialVersionUID = 1L;

                    public void perfomeConfig( JFileChooser jfc )
                    {
                        super.perfomeConfig( jfc );

                        jfc.setFileSelectionMode( JFileChooser.FILES_ONLY );
                        jfc.setMultiSelectionEnabled( true );
                        jfc.setAccessory( new TabbedAccessory()
                                .addTabbedAccessory( new BookmarksAccessory(
                                        jfc,
                                        new DefaultBookmarksAccessoryConfigurator() ) ) );
                    }
                } );
        }
        return jFileChooserInitializer;
    }

    private MiiFileChooser getMiiFileChooser()
    {
        // Check if L&F has change
        String  currentLookAndFeelClassName = UIManager.getLookAndFeel().getClass().getName();

        if( !currentLookAndFeelClassName.equals( miiFileChooserLookAndFeelClassName )) {
            // Look has change is no more valid
            miiFileChooser = null;
            miiFileChooserLookAndFeelClassName = currentLookAndFeelClassName;
        }

        if( jRadioButtonMenuItem1$1FileChooserVFS.isSelected() ) {
            if( !(miiFileChooser instanceof MiiFileChooserVFSImpl) ) {
                miiFileChooser = new MiiFileChooserVFSImpl();
            }
        }
        else {
            if( !(miiFileChooser instanceof MiiFileChooserDefaultImpl) ) {
                miiFileChooser = new MiiFileChooserDefaultImpl( getJFileChooserInitializer() );
            }
        }

        return miiFileChooser;
    }

    protected void setMiiFileObject( MiiFileObject aMiiFileObject )
        throws IOException
    {
        miiFileObject = aMiiFileObject;

        jTextField_FileName.setText( miiFileObject.getDisplayPath() );
        jMenuItem1CheckMii.setEnabled( true );
        jMenuItem0Save.setEnabled( true );

        this.mii_ = miiFileObject.loadMii();
        populate();
    }

    protected void setMiiFileObject( MiiCheckerFileObject aMiiCheckerFileObject )
        throws IOException
    {
        if( miiFileObject != null ) {
            setMiiFileObject(
                miiFileObject.getMiiFileObject(aMiiCheckerFileObject)
                );
        }
    }

    protected MiiFileObject getFileObject()
    {
        return miiFileObject;
    }

    protected String getFileObjectDisplayPath()
    {
        return miiFileObject.getDisplayPath();
    }

    protected String getFileObjectName()
    {
        if( miiFileObject != null ) {
            return miiFileObject.getName();
        }
        else {
            return null;
        }
    }

    protected MiiCheckerFileObject getMiiCheckerFileObject()
    {
        if( miiFileObject == null ) {
            return null;
        }
        else {
            return miiFileObject.getMiiCheckerFileObject();
        }
    }


}

